/*
 * File:   dataProc.h
 * Author: aple
 *
 * Created on 2014年9月15日, 下午8:29
 */

#ifndef DATAPROC_H
#define	DATAPROC_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "stdint.h"
#include "stdlib.h"
#include "string.h"

#define DATA_PROC_ERR_NONE           0x0
#define DATA_PROC_ERR_RES            0x21

	/*******************************************************************************
	* @brief  speed calculate
	*******************************************************************************/
#define uspr_with_speed(speed)     ((60UL * 1000000UL + (speed >> 1)) / speed)                 //输入转速rpm， 返回每转us数
#define us20pr_with_speed(speed)   ((60UL * 1000000UL + ((20 * speed) >> 1)) / (20 * speed))   //输入转速rpm， 返回每转20us数
#define us50pr_with_speed(speed)   ((60UL * 1000000UL + ((50 * speed) >> 1)) / (50 * speed))   //输入转速rpm， 返回每转50us数
#define us100pr_with_speed(speed)  ((60UL * 1000000UL + ((100 * speed) >> 1)) / (100 * speed)) //输入转速rpm， 返回每转100us数
#define rpm_with_us(us)            ((60UL * 1000000UL + (us >> 1)) / us)                       //输入每转us数， 返回转速rpm
#define rpm_m10_with_us(us)        ((600UL * 1000000UL + (us >> 1)) / us)                      //输入每转us数， 返回转速10*rpm
#define rpm_with_clk(clk,  cnt)    ((60UL * clk + (cnt >> 1)) / cnt)                           //输入clk为计数频率(应保证60*clk<2^32)，cnt为每转计数值， 返回转速rpm
#define rpm_m10_with_clk(clk, cnt) ((600UL * clk + (cnt >> 1)) / cnt)                          //输入clk为计数频率(应保证60*clk<2^32)，cnt为每转计数值， 返回转速10*rpm

	/*******************************************************************************
	* @brief  简易逻辑运算
	*******************************************************************************/
#define logic_alloc()      static uint8_t logic_handle_data
#define logic_and_init()   logic_handle_data = 1
#define logic_or_init()    logic_handle_data = 0
#define logic_and(x)       logic_handle_data = logic_handle_data && (x)
#define logic_or(x)        logic_handle_data = logic_handle_data || (x)
#define logic_not()        logic_handle_data = !logic_handle_data
#define logic_get()        logic_handle_data

	// logic calculate
#define lgc_new(x)			if((x)
#define lgc_next(x)			else if((x)
#define lgc_and(x)			&&(x)
#define lgc_or(x)			||(x)
#define lgc_exe()			)

	/*******************************************************************************
	* @brief  loop
	*******************************************************************************/
#define loop_n(x)			for(int index = 0; index < (x); index++)

	// foreach in array
#define forch(array)		for(int index = 0; index<sizeof(array)/sizeof(array[0]);index++)

	/*******************************************************************************
	* @brief  const data
	*******************************************************************************/
	extern uint8_t const led_code[];
	extern uint8_t const ascii_code[];
	extern const uint8_t sinx_0r5pi_256_255[];
	extern uint16_t const sinx_0r5pi_2048_16384[];
	extern uint16_t const sinx2_0r5pi_2048_16384[];
	extern const char hex_ascii_h_tab[];
	extern const char hex_ascii_l_tab[];
	
	/*****************************************************************************
	* @brief  死区.
	*****************************************************************************/
	int32_t dead_zone(int32_t val_real, int32_t val_now, int32_t dead_zone);

	/*****************************************************************************
	* @brief  bcd 转换.
	* \retval: none 、dat
	*****************************************************************************/
	void Hex4ToBCD4(uint16_t Data, uint8_t *Des);
	void Hex4ToBCD8(uint16_t Data, uint8_t *Des);
	void Hex2ToBCD2(uint8_t Data, uint8_t *Des);
	void Hex2ToBCD4(uint8_t Data, uint8_t *Des);

	uint8_t BCD2ToHex(uint8_t Data, uint8_t *Des);
	uint8_t BCD4ToHex(uint16_t Data, uint8_t *Des);
	uint8_t BCD8ToHex(uint32_t Data, uint8_t *Des);

	uint8_t bcd_to_hex_u8(uint8_t bcd);
	uint16_t bcd_to_hex_u16(uint16_t bcd);
	uint32_t bcd_to_hex_u32(uint32_t bcd);
	
	uint8_t hex_to_bcd_u8(uint8_t dat);
	uint16_t hex_to_bcd_u16(uint16_t dat);
	uint32_t hex_to_bcd_u32(uint32_t dat);

	/*******************************************************************************
	* @brief  Hex ascii translate
	*******************************************************************************/
	void hex8_to_ascii(uint32_t Num, uint8_t *Des);
	void hex4_to_ascii(uint16_t Num, uint8_t *Des);
	void hex2_to_ascii(uint8_t Num, uint8_t *Des);

	char hex_to_ascii_lo(uint8_t dat);
	char hex_to_ascii_ho(uint8_t dat);
	
	// len 指定hex长度，尾部加 0
	size_t hex2_to_ascii_multi(const uint8_t *hex, char *ascii, size_t len);
	
	// 遇到非法字符退出， len_max指定最大hex2数量，返回实际转换的hex数量
	size_t ascii_to_hex2_multi(const char *ascii, uint8_t *hex, size_t len_max);
	
	// 遇到0退出，跳过非法字符，len_max指定最大hex2数量，返回实际转换的hex数量
	size_t str_to_hex2(const char *str, uint8_t *hex, size_t len_max);
	
	// 一个HEX字符转换为对应的数值
	uint8_t ascii_to_hex(uint8_t ascii);
	
	// ascii 码转值
	uint8_t ascii_to_hex2(uint8_t *Src);	//2B ascii
	uint16_t ascii_to_hex4(uint8_t *Src);	//4B ascii
	uint32_t ascii_to_hex8(uint8_t *Src);	//8B ascii
	
	/*******************************************************************************
	* @brief  数据位段截取 - 用于安全相关禁止出现数据表的场合
	*******************************************************************************/
	uint32_t code_set_lb(uint32_t src, uint8_t lb);
	uint32_t code_set_hb(uint32_t src, uint8_t hb);
	uint32_t code_set_ub(uint32_t src, uint8_t ub);
	uint32_t code_set_mb(uint32_t src, uint8_t mb);
	uint8_t code_get_lb(uint32_t src);
	uint8_t code_get_hb(uint32_t src);
	uint8_t code_get_ub(uint32_t src);
	uint8_t code_get_mb(uint32_t src);
	uint8_t code_add_u8(uint8_t u1, uint8_t u2);
	uint16_t code_add_u16(uint16_t u1, uint16_t u2);
	uint32_t code_add_u32(uint32_t u1, uint32_t u2);
	uint8_t code_add3_u8(uint8_t u1, uint8_t u2, uint8_t u3);
	uint16_t code_add3_u16(uint16_t u1, uint16_t u2, uint16_t u3);
	uint32_t code_add3_u32(uint32_t u1, uint32_t u2, uint32_t u3);
	uint8_t code_sub_u8(uint8_t u1, uint8_t u2);
	uint16_t code_sub_u16(uint16_t u1, uint16_t u2);
	uint32_t code_sub_u32(uint32_t u1, uint32_t u2);

	//- 获取2的n次方边界值
	uint32_t get_2n_alain_val(uint32_t val);

	/*****************************************************************************
	*          转换结果右对齐
	* @param   Attr:
	*          [7]:   1消零，0补零
	*          [6]:
	*          [5-4]: 小数点位数
	*          [3]:
	*          [2-0]: 十进制结果位数,x+1位
	*****************************************************************************/
	void Int16ToAscii(int16_t Num, uint8_t Attr, uint8_t *Des);
	void Uint16ToAscii(uint16_t Num, uint8_t Attr, uint8_t *Des);

	/*---------------------------------------------------------------------------------*
	* des 目标缓冲， ival 输入值
	* ipn [7:4]整数位数，[3:0]小数位数
	* attr [bit0] 清头零，[bit1]清尾零 ，[bit4]强制显示符号
	*---------------------------------------------------------------------------------*/
	uint8_t i32_to_string(void *des, int32_t ival, uint8_t ip_n, uint8_t attr);

	/*---------------------------------------------------------------------------------*
	* src 字符串 p_n小数位数
	*---------------------------------------------------------------------------------*/
	int32_t string_to_i32(void *src, uint8_t p_n);

	/*****************************************************************************
	*          转换结果左对齐
	* @param   Attr:
	*          [6]:
	*          [5-4]: 小数点位数
	*          [3]:
	*          [2-0]:
	*****************************************************************************/
	uint8_t Uint16ToString(uint16_t Num, uint8_t Attr, uint8_t *Des);
	uint8_t Int16ToString(int16_t Num, uint8_t Attr, uint8_t *Des);

	int16_t AsciiToInt16(uint8_t *pSrc, uint8_t Len);
	int16_t AsciiToInt16_P0(uint8_t *pSrc, uint8_t Len); //无小数
	int16_t AsciiToInt16_P1(uint8_t *pSrc, uint8_t Len); //一位小数

	/*******************************************************************************
	* @brief  i16_to_led_code
	* \param[in] Data : -1999 至 9999
	* \param[in] Des  : 4位输出代码
	* \param[in] zero_clr  : 控制是否清零
	* \param[in] PointSite : 小数点位置
	* \param[in] nodisp : 隐藏位控制，bit[7]控制是否隐藏，bit[1:0]指示隐藏的位 0代表个位，3代表千位
	* \retval: none
	*******************************************************************************/
	void i16_to_led_code(int16_t Data, uint8_t *Des, uint8_t zero_clr, uint8_t PointSite, uint8_t nodisp);

	/*******************************************************************************
	* @brief  i16_to_led_code
	* \param[in] Data : 最大8位数据
	* \param[in] Des  : 输出代码
	* \param[in] zero_clr  : 控制是否清零
	* \param[in] in_ip : in指定有效数据位数，ip指定小数位数
	* \param[in] nodisp : 隐藏位控制，bit[7]控制是否隐藏，bit[2:0] 隐藏位置
	* \retval: none
	*******************************************************************************/
	void i32_to_led_code(int32_t Data, uint8_t *Des, uint8_t zero_clr, uint8_t in_ip, uint8_t nodisp);

	/*******************************************************************************
	* @brief  软件奇偶校验
	*******************************************************************************/
	uint8_t EvenU8(uint8_t Data);                 //返回8位数据的偶校验结果，0表示偶数个1，1表示奇数个1
	uint8_t OddU8(uint8_t Data);                  //返回8位数据的奇校验结果，0表示奇数个1，0表示偶数个1
	uint8_t NoneParity(uint8_t Data);             //返回8位数据的奇校验结果
#define even_u8			EvenU8
#define odd_u8			OddU8
#define parity_none		NoneParity

	/*****************************************************************************
	* @brief  计算累加和.
	* \param[in] dat    源数据
	* \param[in] Len    源数据元素数量
	* \retval: 和结果
	*****************************************************************************/
	int32_t sum_i32(void * dat, uint32_t len); //len 指定元素数量
	int32_t sum_i16(void * dat, uint32_t len);
	int32_t sum_i8(void * dat, uint32_t len);
	uint32_t sum_u32(void * dat, uint32_t len);
	uint32_t sum_u16(void * dat, uint32_t len);
	uint32_t sum_u8(void * dat, uint32_t len);

	/*******************************************************************************
	* @brief  数据舍入
	*******************************************************************************/
	int32_t sub2_add8(float f_real, int32_t i_now); //二舍八入
	int32_t sub_add_x(float f_real, int32_t i_now, float val_sub); //自由舍入，舍入值val_sub[0.1-0.49]
	int32_t int_sub2_add8(int32_t real, int32_t i_now);
	int32_t int_sub_add_x(int32_t real, int32_t i_now, int32_t val_sub);

	/*lrc = ~sum(list)+1 */
	uint8_t lrc_u8(void * dat, uint32_t len); //len 指定元素数量
	uint16_t lrc_u16(void * dat, uint32_t len); //len 指定元素数量
	uint32_t lrc_u32(void * dat, uint32_t len); //len 指定元素数量

	/*xor =  0 xor (list) */
	uint8_t xor_u8(void * dat, uint32_t len); //len 指定元素数量
	uint16_t xor_u16(void * dat, uint32_t len); //len 指定元素数量
	uint32_t xor_u32(void * dat, uint32_t len); //len 指定元素数量

	/*data add.*/
	void dat_add_u8(void *src, uint8_t data, uint32_t Len); //len 指定元素数量
	void dat_add_u16(void *src, uint16_t data, uint32_t Len); //len 指定元素数量
	void dat_add_u32(void *src, uint32_t data, uint32_t Len); //len 指定元素数量
	void dat_sub_u8(void *src, uint8_t data, uint32_t Len); //len 指定元素数量
	void dat_sub_u16(void *src, uint16_t data, uint32_t Len); //len 指定元素数量
	void dat_sub_u32(void *src, uint32_t data, uint32_t Len);  //len 指定元素数量

	/*----------------------------------------------------------------------*
	* 数据记录，数据插在当前索引位置
	* p_list-记录列表，dat-新数据，p_index-索引变量地址， Len列表元素数量
	*-----------------------------------------------------------------------*/
	void record_u8(void *p_list, uint8_t dat, uint16_t* p_index, uint16_t Len);
	void record_u16(void *p_list, uint16_t dat, uint16_t* p_index, uint16_t Len);
	void record_u32(void *p_list, uint32_t dat, uint16_t* p_index, uint16_t Len);

	/*----------------------------------------------------------------------*
	* 数据记录，新数据插在表头，后续数据后移
	* p_list-记录列表，dat-新数据, Len列表长度
	*-----------------------------------------------------------------------*/
	void record_in_first_u8(void *vp_list, uint8_t dat, uint16_t Len);
	void record_in_first_u16(void *vp_list, uint16_t dat, uint16_t Len);
	void record_in_first_u32(void *vp_list, uint32_t dat, uint16_t Len);

	/*--获取数据中 二进制1的个数--*/
	int8_t bit_1_num_get(uint32_t dat, uint8_t start_pos, uint8_t end_pos);
	int8_t bit_0_num_get(uint32_t dat, uint8_t start_pos, uint8_t end_pos);
	uint32_t list_bit_0_num_get(void *list, uint16_t len); //list 为 char
	uint32_t list_bit_1_num_get(void *list, uint16_t len); //list 为 char

	/*--数据按图加减-- des =src1+src2, des=src1-src2*/
	void map_add_u32(uint32_t *src1, uint32_t *src2, uint32_t *des, uint32_t len);//len 指定元素数量
	void map_sub_u32(uint32_t *src1, uint32_t *src2, uint32_t *des, uint32_t len);//len 指定元素数量
	void map_add_u16(uint16_t *src1, uint16_t *src2, uint16_t *des, uint32_t len);//len 指定元素数量
	void map_sub_u16(uint16_t *src1, uint16_t *src2, uint16_t *des, uint32_t len);//len 指定元素数量
	void map_add_u8(uint8_t *src1, uint8_t *src2, uint8_t *des, uint32_t len);    //len 指定元素数量
	void map_sub_u8(uint8_t *src1, uint8_t *src2, uint8_t *des, uint32_t len);    //len 指定元素数量

	//--灯光渐变控制
	typedef struct
	{
		uint8_t IncCoef;  //32-255 Y
		uint8_t bDir;
		uint16_t min;   //Y
		uint16_t max;   //Y
		uint16_t out;
		uint16_t min_keep_time_sv;   //Y
		uint16_t max_keep_time_sv;   //Y
		uint16_t min_keep_time_cnt;
		uint16_t max_keep_time_cnt;
		uint32_t Cal;
	} led_breath_type;
	uint32_t led_breath_handle(led_breath_type *Brj);

	// 步骤管理
	typedef struct
	{
		int32_t time_set;		//Y 计时设定值
		int32_t time_cnt;       //X 计时值，新的step_req时复位
		int32_t time_remain;	//X 剩余时间
		uint16_t step_now;		//X 当前状态
		uint16_t step_req;		//Y 新状态请求
		uint8_t st_new_step;	//X 新状态首次运行标记
		uint8_t st_time_end;	//X 计时结束标记
	} step_manage_type;

	void step_manage_handle(step_manage_type * obj, uint8_t time_pulse);
	void step_manage_reset(step_manage_type * obj);
	void step_manage_req(step_manage_type * obj, uint16_t step_req);



#ifdef	__cplusplus
}
#endif

#endif	/* DATAPROC_H */

